package cn.seaboot.admin.other.manager;

import cn.seaboot.admin.other.bean.SystemProperty;
import cn.seaboot.commons.core.Calculator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.GlobalMemory;
import oshi.hardware.HardwareAbstractionLayer;
import oshi.software.os.FileSystem;
import oshi.software.os.OSFileStore;
import oshi.software.os.OperatingSystem;
import oshi.util.Util;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.*;

/**
 * 系统运行参数
 *
 * @author Mr.css
 * @version 2020-10-09 11:24
 */
@Service
public class RuntimePropertiesService {
    private final Logger logger = LoggerFactory.getLogger(RuntimePropertiesService.class);

    /**
     * 获取全部配置信息
     *
     * @return list
     */
    public List<SystemProperty> getAll() {
        List<SystemProperty> list = new ArrayList<>();
        list.addAll(getComputerInfo());
        list.addAll(getSystemProperties());
        return list;
    }

    /**
     * 计算机属性
     *
     * @return list
     */
    public List<SystemProperty> getComputerInfo() {
        Map<String, String> map = System.getenv();
        List<SystemProperty> list = new ArrayList<>(3);
        list.add(new SystemProperty("username", "用户名", map.get("USERNAME")));
        list.add(new SystemProperty("computer.name", "计算机名", map.get("COMPUTERNAME")));
        list.add(new SystemProperty("user.domain", "计算机域名", map.get("USERDOMAIN")));
        return list;
    }

    /**
     * 获取IP和Max地址
     *
     * @return list
     */
    public List<SystemProperty> getIpConfig() {
        List<SystemProperty> list = new ArrayList<>(2);
        try {
            InetAddress address = InetAddress.getLocalHost();
            NetworkInterface ni = NetworkInterface.getByInetAddress(address);
            byte[] niHardwareAddress = ni.getHardwareAddress();
            StringBuilder mac = new StringBuilder(19);
            for (byte hardwareAddress : niHardwareAddress) {
                String hex = Integer.toHexString(hardwareAddress);
                if (hex.length() == 1) {
                    mac.append("0").append(hex);
                } else {
                    mac.append(hex);
                }
                mac.append('-');
            }
            String ip = address.getHostAddress();
            mac.setLength(mac.length() - 1);
            list.add(new SystemProperty("ip", "局域网IP地址", ip));
            list.add(new SystemProperty("max", "局域网MAC地址", mac.toString()));
        } catch (Exception e) {
            logger.error("获取本地IP异常", e);
        }
        return list;
    }

    /**
     * 获取计算机属性
     *
     * @return list
     */
    public List<SystemProperty> getSystemProperties() {
        Properties props = System.getProperties();
        List<SystemProperty> list = new ArrayList<>(2);

        Map<String, String> mapping = getPropertiesKeys();
        for (Map.Entry<String, String> entry : mapping.entrySet()) {
            list.add(new SystemProperty(entry.getKey(), entry.getValue(), props.getProperty(entry.getKey())));
        }
        return list;
    }

    /**
     * 中文描述
     *
     *
     * // 下面两个好长，不展示了
     * //  map.put("java.class.path", "Java类路径");
     * //  map.put("java.library.path", "加载库时搜索的路径列表");
     *
     * @return list
     */
    public Map<String, String> getPropertiesKeys() {
        Map<String, String> map = new HashMap<>();
        map.put("java.version", "Java运行时环境版本");
        map.put("java.vendor", "Java运行时环境供应商");
        map.put("java.vendor.url", "Java供应商的URL");
        map.put("java.vm.specification.version", "Java虚拟机规范版本");
        map.put("java.vm.specification.vendor", "Java虚拟机规范供应商");
        map.put("java.vm.specification.name", "Java虚拟机规范名称");
        map.put("java.vm.version", "Java虚拟机实现版本");
        map.put("java.vm.vendor", "Java虚拟机实现供应商");
        map.put("java.vm.name", "Java虚拟机实现名称");
        map.put("java.specification.version", "Java运行时环境规范版本");
        map.put("java.specification.vendor", "Java运行时环境规范供应商");
        map.put("java.specification.name", "Java运行时环境规范名称");
        map.put("os.name", "操作系统的名称");
        map.put("os.arch", "操作系统的架构");
        map.put("os.version", "作系统的版本");
        map.put("file.separator", "文件分隔符");
        map.put("path.separator", "路径分隔符");
        map.put("line.separator", "行分隔符");
        map.put("java.home", "JVM目录");
        map.put("java.class.version", "Java类格式版本号");
        map.put("java.io.tmpdir", "默认的临时文件路径");
        map.put("java.compiler", "要使用的JIT编译器的名称");
        map.put("java.ext.dirs", "一个或多个扩展目录的路径");
        map.put("user.name", "用户的账户名称");
        map.put("user.home", "用户的主目录");
        map.put("user.dir", "工作文件夹");
        return map;
    }

    /**
     * CPU 信息
     *
     * @return info
     */
    public Map<String, Object> setCpuInfo() {
        SystemInfo si = new SystemInfo();
        HardwareAbstractionLayer hal = si.getHardware();
        CentralProcessor processor = hal.getProcessor();
        long[] prevTicks = processor.getSystemCpuLoadTicks();
        Util.sleep(1000);

        long[] ticks = processor.getSystemCpuLoadTicks();
        double nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()];
        double irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
        double soft_irq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
        double steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()];

        // CPU 系统使用率
        double sys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
        // CPU 用户使用率
        double used = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()];
        // CPU 当前等待率
        double iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
        // CPU 当前空闲率
        double free = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
        // CPU 总的使用率
        double total = used + nice + sys + free + iowait + irq + soft_irq + steal;

        Map<String, Object> cpu = new HashMap<>();
        // cpu信息
        cpu.put("cpu-card", processor);
        // cpu核心数
        cpu.put("processor-num", processor.getLogicalProcessorCount());
        // cpu 用户使用率;
        cpu.put("used", Calculator.start(sys + used).divide(total).multiply(100).result());
        // cpu 空闲率
        cpu.put("free", Calculator.start(free).divide(total).multiply(100).result());
        return cpu;
    }

    /**
     * 内存信息
     *
     * @return info
     */
    private Map<String, Object> setMemInfo() {
        SystemInfo si = new SystemInfo();
        HardwareAbstractionLayer hal = si.getHardware();
        GlobalMemory memory = hal.getMemory();

        //内存总量
        double total = memory.getTotal();
        //剩余内存
        double free = memory.getAvailable();
        //已用内存
        double used = total - free;

        Map<String, Object> mem = new HashMap<>();
        mem.put("total", total);
        mem.put("used", used);
        mem.put("free", free);
        mem.put("used_percent", Calculator.start(used * 100).divide(total).result());
        mem.put("free_percent", Calculator.start(free * 100).divide(total).result());
        return mem;
    }


    /**
     * Java虚拟机
     *
     * @return info
     */
    public Map<String, Object> setJvmInfo() {
        double total = Runtime.getRuntime().totalMemory();
        double free = Runtime.getRuntime().freeMemory();
        double used = total - free;

        Map<String, Object> jvm = new HashMap<>();
        jvm.put("total_max", Runtime.getRuntime().maxMemory());
        jvm.put("total", total);
        jvm.put("free", used);
        jvm.put("used", used);
        jvm.put("used_percent", Calculator.start(used * 100).divide(total).result());
        jvm.put("free_percent", Calculator.start(free * 100).divide(total).result());
        return jvm;
    }

    /**
     * 设置磁盘信息
     *
     * @return info
     */
    public List<Map<String, Object>> setSysFiles() {
        SystemInfo si = new SystemInfo();
        OperatingSystem os = si.getOperatingSystem();
        FileSystem fileSystem = os.getFileSystem();
        OSFileStore[] fsArray = fileSystem.getFileStores();
        List<Map<String, Object>> list = new ArrayList<>();
        for (OSFileStore fs : fsArray) {
            long free = fs.getUsableSpace();
            long total = fs.getTotalSpace();
            long used = total - free;
            Map<String, Object> map = new HashMap<>();
            map.put("path", fs.getMount());
            map.put("type", fs.getType());
            map.put("name", fs.getName());

            map.put("total", total);
            map.put("used", used);
            map.put("free", free);
            map.put("used_percent", Calculator.start(used * 100).divide(total).result());
            map.put("free_percent", Calculator.start(free * 100).divide(total).result());
            list.add(map);
        }
        return list;
    }
}